﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using MyHealthByDesign.Domain.Processing;

namespace MyHealthByDesign.Domain.Panels
{
    /// <summary>
    /// Description:
    /// MultipleTextBoxes class provides functionality for MultipleTextBox Questions.
    /// 
    /// Author: Mark Servais
    /// Date Created: 10/23/2011
    /// 
    /// Other code files referenced:
    /// IQuestionPanel.cs
    /// 
    /// Regression Test Information:
    /// MultipleTextBoxes_Test.cs in project MyHealthByDesign_Test
    /// 
    /// Revision History:
    /// 10/25/2011 Mark Servais - Added function to retreive question value for type.
    /// 10/27/2011 Mark Servais - Fixed bugs for options and specials.
    /// 10/28/2011 Mark Servais - Fixed Client ID logic.
    /// 11/03/2011 Mark Servais - Added methods to set initial question values from database and 
    ///                             added new CSS options for labels and options
    /// 11/06/2011 Mark Servais - Fixed model help pop-ups by inserting proper style class
    /// 11/22/2011 Mark Servais - Added special processing
    /// 11/22/2011 Mark Servais - Added ability to process attributes for HTML rendering
    /// 12/04/2011 Mark Servais - Added administration form creation and processing
    /// 
    /// Known Faults:
    /// None.
    /// </summary>
    public class MultipleTextBoxes : IQuestionPanel
    {
        private GridView gvFields;

        public struct TBox
        {
            public string FieldName { get; set; }
            public string FieldCSS { get; set; }
            public string FieldSuffix { get; set; }
        }

        #region IQuestionPanel Members

        /// <summary>
        /// GenerateQuestionDisplay - Generates Panel for question to display on
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel control is returned based on question passed
        /// </summary>
        /// <param name="question"></param>
        /// <returns></returns>
        public System.Web.UI.WebControls.Panel GenerateQuestionDisplay(Question question)
        {
            Panel pnlIn = new Panel();
            
            Label lblC = new Label();
            lblC.Text = question.ContentLabel;
            lblC.CssClass = "panelLeft";

            pnlIn.Controls.Add(lblC);

            List<string> FieldNames = new List<string>();
            List<string> FieldSuffixes = new List<string>();
            List<string> FieldCSSs = new List<string>();

            // load Generic Lists
            FieldNames = new List<string>(question.Name.Split('|'));

            if(!string.IsNullOrEmpty(question.FieldCSS))
                FieldCSSs =  new List<string>(question.FieldCSS.Split('|'));

            if (!string.IsNullOrEmpty(question.FieldSuffix))
                FieldSuffixes =  new List<string>(question.FieldSuffix.Split('|'));

            for(int i = 0; i < FieldNames.Count; i++ )
            {
                Type typField = typeof(TextBox).Assembly.GetType("System.Web.UI.WebControls.TextBox");
                TextBox tb = (TextBox)Activator.CreateInstance(typField);
                tb.ID = FieldNames[i];
                tb.ClientIDMode = ClientIDMode.Static;
                if (!string.IsNullOrEmpty(question.FieldCSS))
                    tb.CssClass = FieldCSSs[i];
                
                pnlIn.Controls.Add(tb);

                if (!string.IsNullOrEmpty(question.FieldSuffix))
                {
                    Label lblSuffix = new Label();
                    lblSuffix.Text = "&nbsp;&nbsp;" + FieldSuffixes[i] + "&nbsp;&nbsp;";
                    pnlIn.Controls.Add(lblSuffix);
                }

                // check for special processing
                foreach (QuestionProcessing questionProcessing in question.Processing)
                {
                    if (questionProcessing.FieldName == FieldNames[i])
                    {
                        Type typProcess =
                            typeof(IProcessing).Assembly.GetType(questionProcessing.QuestionProcessingType);
                        IProcessing process = (IProcessing)Activator.CreateInstance(typProcess);

                        process.RunProcessingForField(question, questionProcessing);
                    }
                }

                //apply attributes
                foreach (HtmlAttribute attribute in question.Attributes)
                {
                    if (attribute.ForFieldName == FieldNames[i])
                    {
                        tb.Attributes.Add(attribute.Keyword, attribute.Statement);
                    }
                }
                
            }

            if (!string.IsNullOrEmpty(question.FieldHelpText) && !string.IsNullOrEmpty(question.FieldHelpURL))
            {
                HtmlGenericControl aHelp = new HtmlGenericControl("a");
                aHelp.Attributes.Add("href", question.FieldHelpURL);
                aHelp.Attributes.Add("class", "helplink");
                aHelp.InnerText = question.FieldHelpText;
                pnlIn.Controls.Add(aHelp);
            }

            return pnlIn;
        }

        /// <summary>
        /// RetrieveQuestionValue - Retrieves the question values based on
        /// display type
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Dictionary object is returned with question and fieldname, answer collection
        /// </summary>
        /// <param name="question"></param>
        /// <param name="contentPlaceHolder"></param>
        /// <returns></returns>
        public Dictionary<Question, NameValueCollection> RetrieveQuestionValue(Question question, ContentPlaceHolder contentPlaceHolder)
        {
            Dictionary<Question, NameValueCollection> dFieldValues = new Dictionary<Question, NameValueCollection>();
            NameValueCollection nvc = new NameValueCollection();

            if (question.Name != null)
            {
                List<string> FieldNames = new List<string>(question.Name.Split('|'));

                for (int i = 0; i < FieldNames.Count; i++)
                {
                    TextBox tb = (TextBox)contentPlaceHolder.FindControl(FieldNames[i]);
                    nvc.Add(FieldNames[i], tb.Text);
                }

                dFieldValues.Add(question, nvc); 
            }

            return dFieldValues;
        }

        /// <summary>
        /// SetInitialQuestionValue - Set the question values based on
        /// display type, field name, and databse value
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Field to be placed in panel will be set with database value
        /// </summary>
        /// <param name="question"></param>
        /// <param name="answers"></param>
        /// <param name="contentPlaceHolder"></param>
        public void SetInitialQuestionValue(Question question, NameValueCollection answers, ContentPlaceHolder contentPlaceHolder)
        {
            List<string> FieldNames =  new List<string>(question.Name.Split('|'));

            for (int i = 0; i < FieldNames.Count; i++)
            {
                TextBox tb = (TextBox) contentPlaceHolder.FindControl(FieldNames[i]);
                tb.Text = answers.Get(FieldNames[i]);
            }
        }

        /// <summary>
        /// GenerateAdminForm - Generates Panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel control is returned based on question passed
        /// </summary>
        /// <param name="question"></param>
        /// <param name="panelList"></param>
        /// <returns></returns>
        public List<Panel> GenerateAdminForm(Question question, List<Panel> panelList)
        {
            List<Panel> listPanels = new List<Panel>();
            Panel panelBuild;

            foreach (Panel panel in panelList)
            {
                panelBuild = panel;
                switch (panel.ID)
                {
                    case "pnlQuestionCore":
                        BuildQuestionPanel(ref panelBuild, question);
                        break;
                    case "pnlOptions":
                        BuildOptionPanel(ref panelBuild);
                        break;
                    case "pnlProcessingRules":
                        BuildProcessingPanel(ref panelBuild);
                        break;
                }
                listPanels.Add(panelBuild);

            }

            return listPanels;
        }

        /// <summary>
        /// BuildProcessingPanel - Generates core question panel
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel is updated for collection reference
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private void BuildProcessingPanel(ref Panel panel)
        {
            panel.Visible = false;
            //TODO Add processing logic
        }

        /// <summary>
        /// BuildOptionPanel - Generates core question panel
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel is updated for collection reference
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private void BuildOptionPanel(ref Panel panel)
        {
            panel.Visible = false;
            //TODO Add option logic
        }

        /// <summary>
        /// BuildQuestionPanel - Generates core question panel
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Panel is updated for collection reference
        /// </summary>
        /// <param name="panel"></param>
        /// <returns></returns>
        private void BuildQuestionPanel(ref Panel panel, Question question)
        {
            Domain domain = new Domain();
            bool bUpdate = false;

            if (question.Id != 0)
                bUpdate = true;


            // commonly used controls
            HtmlGenericControl listItem;
            HtmlGenericControl fieldLabel;

            panel.Visible = true;

            // create unordered list
            HtmlGenericControl uList = new HtmlGenericControl("ul");

            // create field type dropdown
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionType");
            fieldLabel.InnerText = "Question Type";

            listItem.Controls.Add(fieldLabel);

            DropDownList ddlQuestionTypes = new DropDownList();
            ddlQuestionTypes.ID = "ddlQuestionTypes";
            ddlQuestionTypes.ClientIDMode = ClientIDMode.Static;

            ddlQuestionTypes.Items.Add(new ListItem("SimpleTextBox", "MyHealthByDesign.Domain.Panels.SimpleTextBox"));
            ddlQuestionTypes.Items.Add(new ListItem("TextBoxWithChecklist", "MyHealthByDesign.Domain.Panels.TextBoxWithChecklist"));
            ddlQuestionTypes.Items.Add(new ListItem("SimpleDropDownList", "MyHealthByDesign.Domain.Panels.SimpleDropDownList"));
            ddlQuestionTypes.Items.Add(new ListItem("SimpleCheckBox", "MyHealthByDesign.Domain.Panels.SimpleCheckBox"));
            ddlQuestionTypes.Items.Add(new ListItem("RangeDropDownList", "MyHealthByDesign.Domain.Panels.RangeDropDownList"));
            ddlQuestionTypes.Items.Add(new ListItem("RadioList", "MyHealthByDesign.Domain.Panels.RadioList"));
            ddlQuestionTypes.Items.Add(new ListItem("MultipleTextBoxes", "MyHealthByDesign.Domain.Panels.MultipleTextBoxes"));
            ddlQuestionTypes.Items.Add(new ListItem("LongLabelMessageBox", "MyHealthByDesign.Domain.Panels.LongLabelMessageBox"));
            ddlQuestionTypes.Items.Add(new ListItem("CheckBoxList", "MyHealthByDesign.Domain.Panels.CheckBoxList"));

            foreach (ListItem item in ddlQuestionTypes.Items)
            {
                if (question.DisplayType == item.Value)
                    item.Selected = true;
                else
                    item.Enabled = false;
            }

            listItem.Controls.Add(ddlQuestionTypes);

            uList.Controls.Add(listItem);

            // create field category dropdown
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionCategory");
            fieldLabel.InnerText = "Question Category";

            listItem.Controls.Add(fieldLabel);

            DropDownList ddlCategories = new DropDownList();
            ddlCategories.ID = "ddlQuestionCategories";
            ddlCategories.ClientIDMode = ClientIDMode.Static;

            List<QuestionCategory> lstCategories = domain.GetCategories();

            // add database items
            foreach (var questionCategory in lstCategories)
            {
                ddlCategories.Items.Add(new ListItem(questionCategory.CategoryDescription, questionCategory.CategoryId.ToString()));
            }

            if (bUpdate)
            {
                foreach (ListItem item in ddlCategories.Items)
                {
                    if (question.Category == Convert.ToInt32(item.Value))
                        item.Selected = true;
                }
            }

            listItem.Controls.Add(ddlCategories);

            uList.Controls.Add(listItem);

            // create field name text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldName");
            fieldLabel.InnerText = "Question Field Name";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldName = new TextBox();
            tbFieldName.ID = "tbFieldName";
            tbFieldName.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldName.Text = question.Name;
            }

            listItem.Controls.Add(tbFieldName);


            RequiredFieldValidator rfvFieldName = new RequiredFieldValidator();
            rfvFieldName.ControlToValidate = "tbFieldName";
            rfvFieldName.Display = ValidatorDisplay.Dynamic;
            rfvFieldName.ErrorMessage = "Field Name is a required field.";
            rfvFieldName.Text = "!";
            rfvFieldName.ForeColor = System.Drawing.Color.Red;

            listItem.Controls.Add(rfvFieldName);

            uList.Controls.Add(listItem);

            // create field label text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldLabel");
            fieldLabel.InnerText = "Question Field Label";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldLabel = new TextBox();
            tbFieldLabel.ID = "tbFieldLabel";
            tbFieldLabel.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldLabel.Text = question.ContentLabel;
            }

            listItem.Controls.Add(tbFieldLabel);

            RequiredFieldValidator rfvFieldLabel = new RequiredFieldValidator();
            rfvFieldLabel.ControlToValidate = "tbFieldLabel";
            rfvFieldLabel.Display = ValidatorDisplay.Dynamic;
            rfvFieldLabel.ErrorMessage = "Field Label is a required field.";
            rfvFieldLabel.Text = "!";
            rfvFieldLabel.ForeColor = System.Drawing.Color.Red;

            listItem.Controls.Add(rfvFieldLabel);

            uList.Controls.Add(listItem);

            // create field css text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldCSS");
            fieldLabel.InnerText = "Question Field CSS";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldCSS = new TextBox();
            tbFieldCSS.ID = "tbFieldCSS";
            tbFieldCSS.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldCSS.Text = question.FieldCSS;
            }

            listItem.Controls.Add(tbFieldCSS);

            uList.Controls.Add(listItem);

            // create field suffix text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldSuffix");
            fieldLabel.InnerText = "Question Field Suffix";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldSuffix = new TextBox();
            tbFieldSuffix.ID = "tbFieldSuffix";
            tbFieldSuffix.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldSuffix.Text = question.FieldSuffix;
            }

            listItem.Controls.Add(tbFieldSuffix);

            uList.Controls.Add(listItem);

            // create field helptext text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldHelpText");
            fieldLabel.InnerText = "Question Field Help Text";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldHelpText = new TextBox();
            tbFieldHelpText.ID = "tbFieldHelpText";
            tbFieldHelpText.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldHelpText.Text = question.FieldHelpText;
            }

            listItem.Controls.Add(tbFieldHelpText);

            uList.Controls.Add(listItem);

            // create field helpURL text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionFieldHelpURL");
            fieldLabel.InnerText = "Question Field Help URL";

            listItem.Controls.Add(fieldLabel);

            TextBox tbFieldHelpURL = new TextBox();
            tbFieldHelpURL.ID = "tbFieldHelpURL";
            tbFieldHelpURL.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                tbFieldHelpURL.Text = question.FieldHelpURL;
            }

            listItem.Controls.Add(tbFieldHelpURL);

            uList.Controls.Add(listItem);

            // create field helpURL text box
            listItem = new HtmlGenericControl("li");
            fieldLabel = new HtmlGenericControl("label");
            fieldLabel.Attributes.Add("for", "questionActive");
            fieldLabel.InnerText = "Question Active";

            listItem.Controls.Add(fieldLabel);

            CheckBox cbQuestionActive = new CheckBox();
            cbQuestionActive.ID = "cbQuestionActive";
            cbQuestionActive.ClientIDMode = ClientIDMode.Static;

            if (bUpdate)
            {
                cbQuestionActive.Checked = question.FieldActive;
            }
            else
            {
                cbQuestionActive.Checked = true;
            }

            listItem.Controls.Add(cbQuestionActive);

            uList.Controls.Add(listItem);

            panel.Controls.Add(uList);

            panel.Visible = true;
        }

        /// <summary>
        /// ProcessAdminForm - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="question"></param>
        /// <param name="panelList"></param>
        /// <returns></returns>
        public void ProcessAdminForm(Question question, List<Panel> panelList)
        {
            Panel panelBuild;

            foreach (Panel panel in panelList)
            {
                panelBuild = panel;
                switch (panel.ID)
                {
                    case "pnlQuestionCore":
                        ProcessQuestionPanel(panelBuild, ref question);
                        break;
                    case "pnlOptions":
                        ProcessOptionPanel(panelBuild);
                        break;
                    case "pnlProcessingRules":
                        ProcessProcessingPanel(panelBuild);
                        break;
                }
            }

            //TODO change to full question update and add
            Domain domain = new Domain();

            if (question.Id != 0)
            {
                domain.UpdateQuestionCore(question);
                domain.UpdateQuestionStatusByValue(question.Id, question.FieldActive);
            }
            else
            {
                //get last sort order
                int lastSort = 0;
                List<Question> listQ = domain.RetrieveQuestions(question.Category);
                foreach (Question q in listQ)
                {
                    lastSort = q.SortOrder;
                }

                question.SortOrder = lastSort + 1;

                int nIdentity = domain.InsertQuestionCore(question);
                if (nIdentity != 0)
                    domain.UpdateQuestionStatusByValue(nIdentity, question.FieldActive);
            }


        }

        /// <summary>
        /// ProcessProcessingPanel - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="panelBuild"></param>
        private void ProcessProcessingPanel(Panel panelBuild)
        {
            //TODO build process logic
        }

        /// <summary>
        /// ProcessOptionPanel - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="panelBuild"></param>
        private void ProcessOptionPanel(Panel panelBuild)
        {
            //TODO build option logic
        }

        /// <summary>
        /// ProcessQuestionPanel - Processes information on panels for question administration
        /// web page
        /// 
        /// PreConditions:
        /// None
        /// 
        /// PostConditions:
        /// Data from fields on panels is entered into the database
        /// </summary>
        /// <param name="panelBuild"></param>
        /// <param name="question"></param>
        private void ProcessQuestionPanel(Panel panelBuild, ref Question question)
        {

            DropDownList ddlQuestionTypes = (DropDownList)panelBuild.FindControl("ddlQuestionTypes");
            question.DisplayType = ddlQuestionTypes.SelectedValue;

            DropDownList ddlCategories = (DropDownList)panelBuild.FindControl("ddlQuestionCategories");
            question.Category = Convert.ToInt32(ddlCategories.SelectedValue);

            TextBox tbFieldName = (TextBox)panelBuild.FindControl("tbFieldName");
            question.Name = tbFieldName.Text;

            TextBox tbFieldLabel = (TextBox)panelBuild.FindControl("tbFieldLabel");
            question.ContentLabel = tbFieldLabel.Text;

            TextBox tbFieldCSS = (TextBox)panelBuild.FindControl("tbFieldCSS");
            question.FieldCSS = tbFieldCSS.Text;

            TextBox tbFieldSuffix = (TextBox)panelBuild.FindControl("tbFieldSuffix");
            question.FieldSuffix = tbFieldSuffix.Text;

            TextBox tbFieldHelpText = (TextBox)panelBuild.FindControl("tbFieldHelpText");
            question.FieldHelpText = tbFieldHelpText.Text;

            TextBox tbFieldHelpURL = (TextBox)panelBuild.FindControl("tbFieldHelpURL");
            question.FieldHelpURL = tbFieldHelpURL.Text;

            CheckBox cbQuestionActive = (CheckBox)panelBuild.FindControl("cbQuestionActive");
            question.FieldActive = cbQuestionActive.Checked;

        }

        #endregion
    }
}